package com.ccteam.fluidmusic.utils.preference

import android.content.Context
import androidx.hilt.work.HiltWorker
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import cn.hutool.core.date.DateUtil
import com.ccteam.fluidmusic.fluidmusic.core.SettingCore
import com.ccteam.fluidmusic.fluidmusic.core.SettingJsonData
import com.ccteam.model.setting.SettingInfoDTO
import com.ccteam.model.setting.SettingInfoEditDTO
import com.ccteam.model.setting.SettingInfoVO
import com.ccteam.network.ApiResult
import com.ccteam.shared.core.UserCore
import com.ccteam.shared.data.user.UserRepository
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject

/**
 * @author Xiaoc
 * @since 2021/4/16
 *
 * 设置项同步到云端数据WorkManager任务
 * 基于WorkManager任务
 *
 * 同步云端数据为以下逻辑：
 * 1.如果登录获取云端用户设置数据
 * 2.如果为空，则同步本地数据至云端
 * 3.如果不为空，判断更新日期，如果云端新则更新本地内容
 *   如果本地新，则更新云端内容
 */
@Suppress("BlockingMethodInNonBlockingContext")
@HiltWorker
class SettingWorker @AssistedInject constructor(
    @Assisted context: Context,
    @Assisted workerParams: WorkerParameters,
    private val settingCore: SettingCore,
    private val userCore: UserCore,
    private val userRepository: UserRepository
): CoroutineWorker(context,workerParams) {

    companion object{
        const val SETTING_WORKER_TAG = "settingWorker"
        const val SETTING_WORKER_ONCE_TAG = "setting_once_worker"
    }

    private val mapper = jacksonObjectMapper()

    override suspend fun doWork(): Result {
        val isLogin = userCore.isLogin.value
        val userInfo = userCore.userInfo.value
        return if(isLogin){
            val result = userRepository.getUserSettingInfo(userInfo.userToken,userInfo.userId)
            if(result !is ApiResult.Success){
                return Result.failure()
            }

            val data = SettingJsonData(
                settingCore.enableFluidMode.value,
                settingCore.lyricTextSize.value,
                settingCore.musicTimer.value.enableTimer,
                settingCore.musicTimer.value.timerCount
            )
            val dataJson = mapper.writeValueAsString(data)
            // 如果返回有数据，则检查是否需要更新数据或更新云端数据
            if(result.data.data != null){
                // 判断是否需要进行更新设置数据，通过updateTime判断
                if(shouldUpdateSetting(result.data.data!!)){

                    val editResult = userRepository.editUserSettingInfo(userInfo.userToken,
                        SettingInfoEditDTO(result.data.data!!.id,userInfo.userId,dataJson)
                    )
                    if(editResult !is ApiResult.Success){
                        return Result.failure()
                    }
                } else {
                    val jsonData = mapper.readValue<SettingJsonData>(result.data.data!!.settingJson)
                    settingCore.updateSetting(jsonData)
                }
                Result.success()
            } else {
                // 如果返回数据为空，代表没有设置内容，需要创建设置内容
                val createResult = userRepository.createUserSettingInfo(userInfo.userToken,
                    SettingInfoDTO(userInfo.userId,dataJson)
                )
                return if(createResult is ApiResult.Success){
                    Result.success()
                } else {
                    Result.failure()
                }
            }
        } else {
            Result.success()
        }
    }

    /**
     * 判断是更新云端设置还是本地设置
     * 如果是云端需要更新，则返回 true
     * 如果是本地需要更新，则返回 false
     */
    private fun shouldUpdateSetting(data: SettingInfoVO): Boolean{
        // 云端的更新日期
        val onlineUpdateTime = DateUtil.parse(data.updateTime,"yyyy-MM-dd HH:mm:ss").time
        val localUpdateTime = settingCore.settingUpdateTime.value

        return (localUpdateTime - onlineUpdateTime) > 0
    }

}
